package app

import (
	"operator/pkg/iptables"
	"operator/pkg/util"
	"strconv"
)

func AddRules() error {
	ipt := iptables.NewIptables()
	//创建inbound链
	_, err := ipt.EnsureChain(iptables.TableNAT, util.SidecarInBoundChain)
	if err != nil {
		return err
	}
	//创建outbound链
	_, err = ipt.EnsureChain(iptables.TableNAT, util.SidecarOutBoundChain)
	if err != nil {
		return err
	}
	//所有流量入inbound链
	//nat表 prerouting链
	_, err = ipt.EnsureRule(iptables.Append, iptables.TableNAT, iptables.ChainPrerouting,
		"-p", "tcp", "-j", util.SidecarInBoundChain)
	if err != nil {
		return err
	}
	//如果是server发送给sidecar的直接进入下一个
	//nat表mesh_inbound链
	_, err = ipt.EnsureRule(iptables.Append, iptables.TableNAT, util.SidecarInBoundChain,
		"-p", "tcp", "-m", "tcp", "--dport", strconv.Itoa(util.TcpServerPort), "-j", "RETURN")
	//如果是发送给sidecar的直接进入下一个
	//nat表mesh_inbound链
	_, err = ipt.EnsureRule(iptables.Append, iptables.TableNAT, util.SidecarInBoundChain,
		"-p", "tcp", "-m", "tcp", "--dport", strconv.Itoa(util.SidecarInBoundPort), "-j", "RETURN")
	if err != nil {
		return err
	}
	//如果是发送给sidecar的直接进入下一个
	//nat表mesh_inbound链
	_, err = ipt.EnsureRule(iptables.Append, iptables.TableNAT, util.SidecarInBoundChain,
		"-p", "tcp", "-m", "tcp", "--dport", strconv.Itoa(util.SidecarOutBoundPort), "-j", "RETURN")
	if err != nil {
		return err
	}

	_, err = ipt.EnsureRule(iptables.Append, iptables.TableNAT, util.SidecarInBoundChain,
		"-d", "127.0.0.1/32", "-j", "RETURN")
	if err != nil {
		return err
	}

	//其余所有流量劫持到本地的inbound port
	//nat表mesh_inbound链
	_, err = ipt.EnsureRule(iptables.Append, iptables.TableNAT, util.SidecarInBoundChain,
		"-p", "tcp", "-m", "tcp", "-j", "REDIRECT", "--to-port", strconv.Itoa(util.SidecarInBoundPort))
	if err != nil {
		return err
	}

	//所有出流量入outbound链
	//nat表 output链
	_, err = ipt.EnsureRule(iptables.Append, iptables.TableNAT, iptables.ChainOutput,
		"-p", "tcp", "-j", util.SidecarOutBoundChain)
	if err != nil {
		return err
	}
	//nat表 mesh_outbound链
	_, err = ipt.EnsureRule(iptables.Append, iptables.TableNAT, util.SidecarOutBoundChain,
		"-d", "127.0.0.1/32", "-j", "RETURN")
	if err != nil {
		return err
	}
	//从sidecar出站且目标地址不为127.0.0.1的流量不执行操作
	//nat表 mesh_outbound链
	_, err = ipt.EnsureRule(iptables.Append, iptables.TableNAT, util.SidecarOutBoundChain,
		"!", "-d", "127.0.0.1/32", "-m", "owner", "--uid-owner", strconv.Itoa(int(util.DefaultSidecarUid)), "-j", "RETURN")
	if err != nil {
		return err
	}
	//其余全部转到outbound
	//nat表 mesh_outbound链
	_, err = ipt.EnsureRule(iptables.Append, iptables.TableNAT, util.SidecarOutBoundChain,
		"-p", "tcp", "-m", "tcp", "-j", "REDIRECT", "--to-port", strconv.Itoa(util.SidecarOutBoundPort))
	if err != nil {
		return err
	}

	return nil
}
